package demo12.javaProxy;

import java.lang.reflect.Proxy;
import java.util.HashMap;

public class MatchMakingTestDrive {
	//map存储数据
HashMap<String, PersonBean> datingDB = new HashMap<String, PersonBean>();
 	//test
	public static void main(String[] args) {
		MatchMakingTestDrive test = new MatchMakingTestDrive();
		test.drive();
	}
 //构造器初始化数据
	public MatchMakingTestDrive() {
		initializeDatabase();
	}

	public void drive() {
		PersonBean xiaoming = getPersonFromDatabase("小明"); //从map中取到名字
		//创建代理（动态代理，运行时创建对象）
		PersonBean ownerProxy = getOwnerProxy(xiaoming);
		//通过代理输出信息
		System.out.println("名字为 " + ownerProxy.getName());
		//改变兴趣
		ownerProxy.setInterests("蓝球");
		System.out.println("从所有者代理设置的兴趣");
		try {
			//改变评级
			ownerProxy.setHotOrNotRating(10);
		} catch (Exception e) {
			System.out.println("无法从所有者代理设置评级");//正常应该无法修改，输出这句
		}
		System.out.println("第一次评级： " + ownerProxy.getHotOrNotRating());

		PersonBean nonOwnerProxy = getNonOwnerProxy(xiaoming);
		System.out.println("名字 ： " + nonOwnerProxy.getName());
		try {
			nonOwnerProxy.setInterests("足球");
		} catch (Exception e) {
			System.out.println("无法设置非所有者代理的兴趣");
		}
		nonOwnerProxy.setHotOrNotRating(3);//可以修改
		System.out.println("非所有者代理的评级集");
		System.out.println("第二次评级： " + nonOwnerProxy.getHotOrNotRating());
	}
/*
 * Proxy这个类的作用就是用来动态创建一个代理对象的类，它提供了许多的方法，
 *    但是我们用的最多的就是 newProxyInstance 这个方法：
 *    这个方法的作用就是得到一个动态的代理对象，其接收三个参数，这三个参数所代表的含义：
  * 通过Proxy的newProxyInstance方法来创建我们的代理对象，我们来看看其三个参数
     Proxy.newProxyInstance方法会做如下几件事：

1，根据传入的第二个参数interfaces动态生成一个类，实现interfaces中的接口，该例中即BusinessProcessor接口的processBusiness方法。并且继承了Proxy类，重写了hashcode,toString,equals等三个方法。具体实现可参看 ProxyGenerator.generateProxyClass(...); 该例中生成了$Proxy0类

2，通过传入的第一个参数classloder将刚生成的类加载到jvm中。即将$Proxy0类load

3，利用第三个参数，调用$Proxy0的$Proxy0(InvocationHandler)构造函数 创建$Proxy0的对象，并且用interfaces参数遍历其所有接口的方法，并生成Method对象初始化对象的几个Method成员变量

4，将$Proxy0的实例返回给客户端。
 * */
	//创建自己的代理
	PersonBean getOwnerProxy(PersonBean person) {
 		
        return (PersonBean) Proxy.newProxyInstance( 
            	person.getClass().getClassLoader(),
            	person.getClass().getInterfaces(),
                new OwnerInvocationHandler(person));
	}
//创建非本人代理
	PersonBean getNonOwnerProxy(PersonBean person) {
		
        return (PersonBean) Proxy.newProxyInstance(
            	person.getClass().getClassLoader(),
            	person.getClass().getInterfaces(),
                new NonOwnerInvocationHandler(person));
	}
//返回map中的name数据
	PersonBean getPersonFromDatabase(String name) {
		return (PersonBean)datingDB.get(name);
	}
//模拟存入数据
	void initializeDatabase() {
		PersonBean joe = new PersonBeanImpl();
		joe.setName("小明");
		joe.setInterests("汽车，电脑，音乐");
		joe.setHotOrNotRating(7);//评级7
		datingDB.put(joe.getName(), joe);

		PersonBean kelly = new PersonBeanImpl();
		kelly.setName("小红");
		kelly.setInterests("易趣网，电影，音乐");
		kelly.setHotOrNotRating(6);
		datingDB.put(kelly.getName(), kelly);
	}
}
/*
 名字为 小明
从所有者代理设置的兴趣
无法从所有者代理设置评级
第一次评级： 7
名字 ： 小明
无法设置非所有者代理的兴趣
非所有者代理的评级集
第二次评级： 5*/
